{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "afc6bd0e-ca34-49ad-8725-7cbf9dd135b4",
   "metadata": {},
   "source": [
    "首字母大写的变量为导出变量，具有公共可见性，可被其他包访问。\n",
    "\n",
    "首字母小写的变量为未导出变量，具有私有可见性，只能在定义它的包内部访问。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34b177cb-7317-4614-b475-5ea51a50b30f",
   "metadata": {},
   "source": [
    "常量表达式中，函数必须是内置函数，否则编译不过。\n",
    "\n",
    "iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前)，const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0dcc97c3-c40d-4904-b387-44de806b7b0f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 2 ha ha 100 100 7 8\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func main() {\n",
    "    const (\n",
    "            a = iota   //0\n",
    "            b          //1\n",
    "            c          //2\n",
    "            d = \"ha\"   //独立值，iota += 1\n",
    "            e          //\"ha\"   iota += 1\n",
    "            f = 100    //iota +=1\n",
    "            g          //100  iota +=1\n",
    "            h = iota   //7,恢复计数\n",
    "            i          //8\n",
    "    )\n",
    "    fmt.Println(a,b,c,d,e,f,g,h,i)\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f1804bd-aa4c-4efe-be3e-f8fc5a5c188f",
   "metadata": {},
   "source": [
    "Go 语言最少有个 main() 函数\n",
    "```text\n",
    "func function_name( [parameter list] ) [return_types] {\n",
    "   函数体\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "1ceb9728-2e03-400c-a4ca-d0011b0945e3",
   "metadata": {},
   "outputs": [
    {
     "ename": "ERROR",
     "evalue": "repl.go:6:4: return: expecting 0 expressions, found 2: return y, x",
     "output_type": "error",
     "traceback": [
      "repl.go:6:4: return: expecting 0 expressions, found 2: return y, x"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func swap(x string, y string){\n",
    "   return y, x\n",
    "}\n",
    "\n",
    "func main() {\n",
    "   a, b := swap(\"Google\", \"Runoob\")\n",
    "   fmt.Println(a, b)\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "01b1162a-75b0-473f-8315-2026b71f991a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Runoob Google\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func swap(x string, y string)(string,string){\n",
    "   return y, x\n",
    "}\n",
    "\n",
    "func main() {\n",
    "   a, b := swap(\"Google\", \"Runoob\")\n",
    "   fmt.Println(a, b)\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c3bdfc7-5064-40d5-88ac-c45975e9c6aa",
   "metadata": {},
   "source": [
    "奇奇怪怪，返回类型不能省略"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "e4bae0c4-9b57-4d28-83e8-bb519bc813cf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Runoob Google\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func swap(x, y string)(string,string){\n",
    "   return y, x\n",
    "}\n",
    "\n",
    "func main() {\n",
    "   a, b := swap(\"Google\", \"Runoob\")\n",
    "   fmt.Println(a, b)\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37655150-60c8-4e78-a722-5884a5096635",
   "metadata": {},
   "source": [
    "参数类型也不能省略，如果相同的参数，可以只在最后面写"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "1487960c-bd07-408e-8c52-f0ffc9b4e559",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Runoob Google 123\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func swap(x, y string,c int)(string,string,int){\n",
    "   return y, x, c\n",
    "}\n",
    "\n",
    "func main() {\n",
    "   a, b, c := swap(\"Google\", \"Runoob\",123)\n",
    "   fmt.Println(a, b, c)\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6a563c7d-b2d9-44c0-a62b-6e7f06ad3d00",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "numbers := [5]int{1, 2, 3, 4, 5}\n",
    "numbers[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c9b95f22-e886-4f57-89f0-23cb7d3078a1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[1 2 3] [4 5 6]]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "matrix := [2][3]int{{1,2,3},{4,5,6}}\n",
    "matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "17441fda-e8da-4ea8-b16d-d9365356927d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a :=20\n",
    "b := &a\n",
    "c := a\n",
    "*b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "1850562e-ce3c-448c-af75-42ae41705214",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "25"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a += 5\n",
    "*b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "f04bce96-b92d-4619-96bb-6c2f4317624a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "dfe5e0e0-14f6-4a30-84be-a1b54d802cca",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Book title : Go 语言\n",
      "Book author : www.runoob.com\n",
      "Book subject : Go 语言教程\n",
      "Book book_id : 6495407\n",
      "Book title : Python 教程\n",
      "Book author : www.runoob.com\n",
      "Book subject : Python 语言教程\n",
      "Book book_id : 6495700\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "type Books struct {\n",
    "   title string\n",
    "   author string\n",
    "   subject string\n",
    "   book_id int\n",
    "}\n",
    "\n",
    "func main() {\n",
    "   var Book1 Books        /* 声明 Book1 为 Books 类型 */\n",
    "   var Book2 Books        /* 声明 Book2 为 Books 类型 */\n",
    "\n",
    "   /* book 1 描述 */\n",
    "   Book1.title = \"Go 语言\"\n",
    "   Book1.author = \"www.runoob.com\"\n",
    "   Book1.subject = \"Go 语言教程\"\n",
    "   Book1.book_id = 6495407\n",
    "\n",
    "   /* book 2 描述 */\n",
    "   Book2.title = \"Python 教程\"\n",
    "   Book2.author = \"www.runoob.com\"\n",
    "   Book2.subject = \"Python 语言教程\"\n",
    "   Book2.book_id = 6495700\n",
    "\n",
    "   /* 打印 Book1 信息 */\n",
    "   printBook(&Book1)\n",
    "\n",
    "   /* 打印 Book2 信息 */\n",
    "   printBook(&Book2)\n",
    "}\n",
    "func printBook( book *Books ) {\n",
    "   fmt.Printf( \"Book title : %s\\n\", book.title)\n",
    "   fmt.Printf( \"Book author : %s\\n\", book.author)\n",
    "   fmt.Printf( \"Book subject : %s\\n\", book.subject)\n",
    "   fmt.Printf( \"Book book_id : %d\\n\", book.book_id)\n",
    "}\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b626b012-d325-4089-ab7d-daf8b06c5336",
   "metadata": {},
   "source": [
    "指针作为参数，传入的应该是地址"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "609234de-016f-4079-a93d-220590ea6fe3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "22\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "import \"fmt\"\n",
    "\n",
    "func main(){\n",
    "    a := 20\n",
    "    b := testPointer(&a)\n",
    "    fmt.Println(b)\n",
    "}\n",
    "\n",
    "func testPointer(b *int) int{\n",
    "    return *b+2\n",
    "}\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "c9ac7858-d8f9-402a-ba25-f7ba7f1892e5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{Go 语言 www.runoob.com Go 语言教程 6495407}"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type Books struct {\n",
    "   title string\n",
    "   author string\n",
    "   subject string\n",
    "   book_id int\n",
    "}\n",
    "Book1 := Books{title: \"Go 语言\", author: \"www.runoob.com\", subject: \"Go 语言教程\", book_id: 6495407}\n",
    "Book1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "184cb66d-54e0-4f76-b52a-a52cb2f7d7ce",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{   0}"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Books()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "e6af07d9-1e8c-429a-bd82-6a858b2f0a50",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "&{Go 语言 www.runoob.com Go 语言教程 6495407}"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Book2 := &Book1\n",
    "Book2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "0228593f-4d87-427b-ae16-eb652d33f577",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Go 语言"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Book2.title"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "cd72f6ec-c159-45b8-a924-a17429b34ddb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{Go 语言 www.runoob.com Go 语言教程 6495407}"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "*Book2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cdef5061-7b89-4534-8026-15f02f1a44e1",
   "metadata": {},
   "source": [
    "奇奇怪怪的，结构体的地址就是&加结构体本身，难怪了上面指针传参没用用*号获得值……"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "ac1e1929-51f7-4b92-9b0d-10ddb61b05c0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 2 3 4]"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s := [] int{1,2,3,4}\n",
    "s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "6b33ec15-365e-4302-a42f-f860f5b025c9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cap(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "e4ffa5f4-5d05-4ebb-a610-485747603246",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 2 3]"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s[:3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "cff7fc38-f14f-4a36-9176-5f57b7a80e6f",
   "metadata": {},
   "outputs": [],
   "source": [
    "s = append(s,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "f2452d6f-f740-4c44-9d75-8e251460322f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cap(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "d72c5b4e-8874-484c-b35a-90345a686058",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3e547931-09c7-43e7-819e-cc175677b410",
   "metadata": {},
   "source": [
    "直接将初始的切片扩容为double,所以一开始设置容量大小也是不错的选择"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "aedd769b-356e-4be8-98f0-1f336eb81435",
   "metadata": {},
   "outputs": [],
   "source": [
    "s := make([]int,4,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "d75a32e0-8971-4ca4-80ca-d63278217c9d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0 0 0 0]"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "3298c6df-cd99-4979-aaa7-2ffc7c3b29a1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s==nil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "f43e9cba-0ef9-4113-99bd-4c327a153e73",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s := []int{}\n",
    "s==nil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "d6d4d659-842a-45af-9796-fa26b39962bd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "var s []int\n",
    "s==nil"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a409bdd3-b746-44c1-95a2-fc9b96f943dd",
   "metadata": {},
   "source": [
    "只声明是nil表示为空,其余方式都是有默认填充值为0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "49290a8a-56bb-4d3e-be65-91396c27e3e8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 2 3 4]"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s := make([]int,4,5)\n",
    "l := [] int{1,2,3,4}\n",
    "copy(s,l)\n",
    "s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "8dc9a5f5-2249-48ac-a5e1-64d6caaf9e4c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cap(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "39bde5d8-0c25-4347-b691-05b4f4a7abeb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "id": "cad286c7-6ee4-4b8c-a7ce-e4079a262953",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10\n",
      "20\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func main() {\n",
    "    var a chan int\n",
    "    a = make(chan int)\n",
    "    go func() {\n",
    "        a <- 10\n",
    "        a <- 20\n",
    "        close(a)\n",
    "    }()\n",
    "    num := <-a\n",
    "    fmt.Println(num)\n",
    "    num = <- a\n",
    "    fmt.Println(num)\n",
    "}\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "id": "341e28c1-5a51-4edd-8548-2bcfcc30569b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2**0 = 1\n",
      "2**1 = 2\n",
      "2**2 = 4\n",
      "2**3 = 8\n",
      "2**4 = 16\n",
      "2**5 = 32\n",
      "2**6 = 64\n",
      "2**7 = 128\n",
      "\n",
      "index: 0, char: h\n",
      "index: 1, char: e\n",
      "index: 2, char: l\n",
      "index: 3, char: l\n",
      "index: 4, char: o\n",
      "\n",
      "1 1\n",
      "2 2\n",
      "hell 3\n",
      "\n",
      "b -> banana\n",
      "a -> apple\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "// 声明一个包含 2 的幂次方的切片\n",
    "var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}\n",
    "\n",
    "func main() {\n",
    "    for i, v := range pow {\n",
    "        fmt.Printf(\"2**%d = %d\\n\", i, v)\n",
    "    }\n",
    "    fmt.Println()\n",
    "    \n",
    "    for i, c := range \"hello\" {\n",
    "        fmt.Printf(\"index: %d, char: %c\\n\", i, c)\n",
    "    }\n",
    "    fmt.Println()\n",
    "\n",
    "    map1 := make(map[any]float32)\n",
    "    map1[1] = 1.0\n",
    "    map1[2] = 2.0\n",
    "    map1[\"hell\"] = 3.0\n",
    "    for k,v := range map1{\n",
    "        fmt.Println(k,v)\n",
    "    }\n",
    "    fmt.Println()\n",
    "\n",
    "    kvs := map[string]string{\"a\": \"apple\", \"b\": \"banana\"}\n",
    "    for k, v := range kvs {\n",
    "        fmt.Printf(\"%s -> %s\\n\", k, v)\n",
    "    }\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a37dd373-ae53-45f3-a89c-9676793ea288",
   "metadata": {},
   "source": [
    "数组、切片、字典初始化有初始值和用make进行初始值为0的初始化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "id": "702cb7ec-2962-4c4d-b3c2-40f0e55588ad",
   "metadata": {},
   "outputs": [
    {
     "ename": "ERROR",
     "evalue": "repl.go:1:9: expected expression",
     "output_type": "error",
     "traceback": [
      "repl.go:1:9: expected expression"
     ]
    }
   ],
   "source": [
    "map2 := map[any]float32\n",
    "map2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "id": "b1375583-edde-4929-af9e-87772c22349d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "map[]"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map2 := map[string]float32{}\n",
    "map2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "2835571b-5602-4c74-9b06-067f70c3a850",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "map[Baidu:百度 Google:谷歌 Runoob:菜鸟教程 Wiki:维基百科]"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "siteMap := make(map[string]string,5)\n",
    "siteMap [ \"Google\" ] = \"谷歌\"\n",
    "siteMap [ \"Runoob\" ] = \"菜鸟教程\"\n",
    "siteMap [ \"Baidu\" ] = \"百度\"\n",
    "siteMap [ \"Wiki\" ] = \"维基百科\"\n",
    "siteMap"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "id": "4c2089bd-3169-42e9-880d-73c19d32335d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "siteMap[\"Facebook\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "id": "282d8524-5348-4943-8a72-7a5d4f52eb05",
   "metadata": {},
   "outputs": [
    {
     "ename": "ERROR",
     "evalue": "repl.go:1:5: cannot use siteMap <map[string]string> as array, channel, slice, pointer to array in builtin cap()",
     "output_type": "error",
     "traceback": [
      "repl.go:1:5: cannot use siteMap <map[string]string> as array, channel, slice, pointer to array in builtin cap()"
     ]
    }
   ],
   "source": [
    "cap(siteMap)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "id": "6cf8f70e-1bce-40d1-8b74-e5cfb372cd94",
   "metadata": {},
   "outputs": [],
   "source": [
    "delete(siteMap,\"Facebook\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "id": "90f64627-b7d1-478a-a981-1f747a9377cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "delete(siteMap,\"Runoob\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "id": "e62554e9-33e0-43ab-8193-33ed315a1521",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "map[Baidu:百度 Google:谷歌 Wiki:维基百科]"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "siteMap"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "id": "32841579-5668-486c-be62-6390b88bc3d9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "func Factorial(n int)int{\n",
    "    if n>0{\n",
    "        return n*Factorial(n-1)\n",
    "    }\n",
    "    return 1\n",
    "}\n",
    "Factorial(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "18aa1002-dab4-450a-94a3-d46b8a56248e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1307674368000"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Factorial(15)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6619b7df-bb31-4324-9988-04147e6a68a8",
   "metadata": {},
   "source": [
    "`new_guess = (guess + n / guess) / 2` 这一步是牛顿迭代法在求解平方根问题时的核心迭代公式，下面从原理、几何意义和推导过程等方面详细解释这一步：\n",
    "\n",
    "**牛顿迭代法原理**\n",
    "\n",
    "牛顿迭代法是一种用于求解方程根的数值方法，其基本思想是利用函数的泰勒级数展开的一阶近似，通过不断迭代来逼近函数的根。对于一个可导函数 $f(x)$，我们想要找到方程 $f(x) = 0$ 的根，牛顿迭代法的迭代公式为：\n",
    "\n",
    "$$x_{k + 1}=x_{k}-\\frac{f(x_{k})}{f^{\\prime}(x_{k})}$$\n",
    "\n",
    "其中，$x_{k}$ 是第 $k$ 次迭代的近似根，$x_{k + 1}$ 是第 $k + 1$ 次迭代的近似根，$f^{\\prime}(x_{k})$ 是函数 $f(x)$ 在 $x_{k}$ 处的导数。\n",
    "\n",
    "**求解平方根问题的函数设定**\n",
    "\n",
    "要求一个数 $n$ 的平方根，等价于求解方程 $f(x)=x^{2}-n = 0$ 的正根。因为当 $x = \\sqrt{n}$ 时，$x^{2}-n$ 的值为 0。\n",
    "\n",
    "**推导迭代公式**\n",
    "\n",
    "1. 首先求函数 $f(x)=x^{2}-n$ 的导数：\n",
    "根据求导公式 $(X^n)^\\prime = nX^{n - 1}$，可得 $f^{\\prime}(x)=2x$。\n",
    "2. 然后将 $f(x)$ 和 $f^{\\prime}(x)$ 代入牛顿迭代法的迭代公式：\n",
    "$$x_{k + 1}=x_{k}-\\frac{f(x_{k})}{f^{\\prime}(x_{k})}=x_{k}-\\frac{x_{k}^{2}-n}{2x_{k}}$$\n",
    "3. 对上式进行化简：\n",
    "$$\n",
    "\\begin{align*}\n",
    "x_{k + 1}&=x_{k}-\\frac{x_{k}^{2}-n}{2x_{k}}\\\\\n",
    "&=\\frac{2x_{k}^{2}-(x_{k}^{2}-n)}{2x_{k}}\\\\\n",
    "&=\\frac{2x_{k}^{2}-x_{k}^{2}+n}{2x_{k}}\\\\\n",
    "&=\\frac{x_{k}^{2}+n}{2x_{k}}\\\\\n",
    "&=\\frac{x_{k}+\\frac{n}{x_{k}}}{2}\n",
    "\\end{align*}\n",
    "$$\n",
    "\n",
    "在代码中，`guess` 对应 $x_{k}$，`new_guess` 对应 $x_{k + 1}$，`n` 就是要求平方根的数，所以 `new_guess = (guess + n / guess) / 2` 就是上述推导得到的迭代公式。\n",
    "\n",
    "**几何意义**\n",
    "\n",
    "从几何角度来看，牛顿迭代法的每一次迭代都是在当前点 $(x_{k}, f(x_{k}))$ 处作函数 $f(x)$ 的切线，然后找到该切线与 $x$ 轴的交点作为下一次迭代的近似根。对于函数 $f(x)=x^{2}-n$，通过不断地作切线并找到切线与 $x$ 轴的交点，逐渐逼近函数的根 $\\sqrt{n}$。\n",
    "\n",
    "**迭代过程**\n",
    "\n",
    "在代码实现中，我们从一个初始猜测值 `guess` 开始，不断使用迭代公式更新猜测值，直到满足一定的终止条件（如当前猜测值的平方与目标数的差的绝对值小于某个允许的误差范围），此时的猜测值就可以作为平方根的近似值。\n",
    "\n",
    "通过不断迭代，猜测值会越来越接近 $\\sqrt{n}$，最终得到一个满足精度要求的近似解。 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34875de9-ce37-4627-b651-6c1cb252ecc2",
   "metadata": {},
   "source": [
    "**带佩亚诺型余项的泰勒公式**\n",
    "\n",
    "设函数$f(x)$在点$x_0$处具有$n$阶导数，那么存在$x_0$的一个邻域，对于该邻域内任一$x$，有\n",
    "$$f(x)=f(x_0)+f'(x_0)(x - x_0)+\\frac{f''(x_0)}{2!}(x - x_0)^2+\\cdots+\\frac{f^{(n)}(x_0)}{n!}(x - x_0)^n+R_n(x)$$\n",
    "其中，$R_n(x)=o((x - x_0)^n)$，表示当$x\\to x_0$时，$R_n(x)$是比$(x - x_0)^n$高阶的无穷小。这种形式的余项被叫做佩亚诺型余项。\n",
    "\n",
    "**带拉格朗日型余项的泰勒公式**\n",
    "\n",
    "设函数$f(x)$在包含$x_0$的某个开区间$(a,b)$内具有直到$n + 1$阶的导数，则对任意$x\\in(a,b)$，有\n",
    "$$f(x)=f(x_0)+f'(x_0)(x - x_0)+\\frac{f''(x_0)}{2!}(x - x_0)^2+\\cdots+\\frac{f^{(n)}(x_0)}{n!}(x - x_0)^n+R_n(x)$$\n",
    "这里的$R_n(x)=\\frac{f^{(n + 1)}(\\xi)}{(n+1)!}(x - x_0)^{n + 1}$，其中$\\xi$介于$x$与$x_0$之间。此形式的余项就是拉格朗日型余项。\n",
    "\n",
    "**麦克劳林公式**\n",
    "\n",
    "当$x_0 = 0$时，泰勒公式就变成了麦克劳林公式：\n",
    "$$f(x)=f(0)+f'(0)x+\\frac{f''(0)}{2!}x^2+\\cdots+\\frac{f^{(n)}(0)}{n!}x^n+R_n(x)$$\n",
    "佩亚诺型余项$R_n(x)=o(x^n)$，拉格朗日型余项$R_n(x)=\\frac{f^{(n + 1)}(\\theta x)}{(n + 1)!}x^{n + 1}$（$0<\\theta<1$）。\n",
    "\n",
    "**常见函数的泰勒级数展开**\n",
    "\n",
    "指数函数$e^x$\n",
    "$$e^x = 1 + x+\\frac{x^2}{2!}+\\frac{x^3}{3!}+\\cdots+\\frac{x^n}{n!}+R_n(x),\\quad x\\in(-\\infty,+\\infty)$$\n",
    "这里$R_n(x)=\\frac{e^{\\xi}}{(n + 1)!}x^{n + 1}$，$\\xi$介于$0$与$x$之间。\n",
    "\n",
    "正弦函数$\\sin x$\n",
    "$$\\sin x=x-\\frac{x^3}{3!}+\\frac{x^5}{5!}-\\frac{x^7}{7!}+\\cdots+(-1)^{k}\\frac{x^{2k + 1}}{(2k+1)!}+R_{2k + 1}(x),\\quad x\\in(-\\infty,+\\infty)$$\n",
    "其中$R_{2k + 1}(x)=\\frac{\\sin(\\xi+(k + 1)\\pi)}{(2k + 2)!}x^{2k + 2}$，$\\xi$介于$0$与$x$之间。\n",
    "\n",
    "余弦函数$\\cos x$\n",
    "$$\\cos x = 1-\\frac{x^2}{2!}+\\frac{x^4}{4!}-\\frac{x^6}{6!}+\\cdots+(-1)^{k}\\frac{x^{2k}}{(2k)!}+R_{2k}(x),\\quad x\\in(-\\infty,+\\infty)$$\n",
    "其中$R_{2k}(x)=\\frac{\\cos(\\xi+(k + 1)\\pi)}{(2k+1)!}x^{2k + 1}$，$\\xi$介于$0$与$x$之间。\n",
    "\n",
    "**应用场景**\n",
    "\n",
    "- **数值计算**：用泰勒多项式近似代替复杂函数，从而简化计算。\n",
    "- **误差分析**：借助余项估计近似计算所产生的误差。\n",
    "- **函数性质研究**：通过泰勒级数来分析函数的局部性质，像单调性、凹凸性等。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "id": "5664b77a-da99-46d5-b95f-f911081776e6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.82842712474619"
      ]
     },
     "execution_count": 114,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "func sqrt(n,x,tolerate float64)(float64){\n",
    "    if -tolerate <x*x - n && x*x - n< tolerate{\n",
    "        return x\n",
    "    }\n",
    "    return sqrt(n,(x+n/x)/2,tolerate)\n",
    "}\n",
    "\n",
    "sqrt(8.0,1.0,1e-9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "60ef8b54-3c98-4594-a3f2-00fe267a5dd7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'Hello, World' is a string\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func main() {\n",
    "    var i interface{} = \"Hello, World\"\n",
    "    str, ok := i.(string)\n",
    "    if ok {\n",
    "        fmt.Printf(\"'%s' is a string\\n\", str)\n",
    "    } else {\n",
    "        fmt.Println(\"conversion failed\")\n",
    "    }\n",
    "}\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce5b84d2-9ae3-489d-9e8a-fc9336c16329",
   "metadata": {},
   "source": [
    "接口（interface）是 Go 语言中的一种类型，用于定义行为的集合，它通过描述类型必须实现的方法，规定了类型的行为契约。\n",
    "\n",
    "Go 语言提供了另外一种数据类型即接口，它把所有的具有共性的方法定义在一起，任何其他类型只要实现了这些方法就是实现了这个接口。\n",
    "\n",
    "Go 的接口设计简单却功能强大，是实现多态和解耦的重要工具。\n",
    "\n",
    "接口可以让我们将不同的类型绑定到一组公共的方法上，从而实现多态和灵活的设计。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb7d17f4-d4bf-46b9-9dbe-a18b4f322531",
   "metadata": {},
   "source": [
    "在 Go 语言里，定义接口（像代码中的 `Shape` 接口）有诸多作用，即便在当前代码里不定义接口也能实现相同的功能，不过接口的存在能让代码更具灵活性、可扩展性和可维护性。下面为你详细分析定义 `Shape` 接口的作用以及与不使用接口的差异。\n",
    "\n",
    "**1. 代码复用与扩展性**\n",
    "\n",
    "在当前代码里，仅定义了一个 `Circle` 结构体，但要是后续需要添加更多的几何形状，例如矩形、三角形等，接口的优势就会体现出来。\n",
    "\n",
    "**示例代码** \n",
    "```go\n",
    "package main\n",
    "\n",
    "import (\n",
    "    \"fmt\"\n",
    "    \"math\"\n",
    ")\n",
    "\n",
    "// 定义接口\n",
    "type Shape interface {\n",
    "    Area() float64\n",
    "    Perimeter() float64\n",
    "}\n",
    "\n",
    "// 定义一个结构体\n",
    "type Circle struct {\n",
    "    Radius float64\n",
    "}\n",
    "\n",
    "// Circle 实现 Shape 接口\n",
    "func (c Circle) Area() float64 {\n",
    "    return math.Pi * c.Radius * c.Radius\n",
    "}\n",
    "\n",
    "func (c Circle) Perimeter() float64 {\n",
    "    return 2 * math.Pi * c.Radius\n",
    "}\n",
    "\n",
    "// 定义矩形结构体\n",
    "type Rectangle struct {\n",
    "    Width  float64\n",
    "    Height float64\n",
    "}\n",
    "\n",
    "// Rectangle 实现 Shape 接口\n",
    "func (r Rectangle) Area() float64 {\n",
    "    return r.Width * r.Height\n",
    "}\n",
    "\n",
    "func (r Rectangle) Perimeter() float64 {\n",
    "    return 2 * (r.Width + r.Height)\n",
    "}\n",
    "\n",
    "// 计算任意形状的面积和周长\n",
    "func printShapeInfo(s Shape) {\n",
    "    fmt.Println(\"Area:\", s.Area())\n",
    "    fmt.Println(\"Perimeter:\", s.Perimeter())\n",
    "}\n",
    "\n",
    "func main() {\n",
    "    c := Circle{Radius: 5}\n",
    "    r := Rectangle{Width: 4, Height: 6}\n",
    "\n",
    "    fmt.Println(\"Circle Info:\")\n",
    "    printShapeInfo(c)\n",
    "\n",
    "    fmt.Println(\"\\nRectangle Info:\")\n",
    "    printShapeInfo(r)\n",
    "}\n",
    "```\n",
    "\n",
    "**解释**\n",
    "- 定义了 `Shape` 接口后，新增的 `Rectangle` 结构体只需实现 `Area()` 和 `Perimeter()` 方法，就能被视为 `Shape` 类型。\n",
    "- `printShapeInfo` 函数接收一个 `Shape` 类型的参数，这样就可以处理任意实现了 `Shape` 接口的类型，避免了为每种形状都编写一个单独的函数，提高了代码的复用性。\n",
    "\n",
    "**2. 依赖倒置与松耦合**\n",
    "\n",
    "接口能够实现依赖倒置原则，降低代码之间的耦合度。例如，在一个更复杂的系统中，某个模块可能需要处理各种形状，但并不关心具体是哪种形状，只需要知道这些形状都有计算面积和周长的方法即可。\n",
    "\n",
    "**示例代码**\n",
    "\n",
    "```go\n",
    "package main\n",
    "\n",
    "import (\n",
    "    \"fmt\"\n",
    "    \"math\"\n",
    ")\n",
    "\n",
    "// 定义接口\n",
    "type Shape interface {\n",
    "    Area() float64\n",
    "    Perimeter() float64\n",
    "}\n",
    "\n",
    "// 某个模块，依赖 Shape 接口\n",
    "func processShapes(shapes []Shape) {\n",
    "    for _, shape := range shapes {\n",
    "        fmt.Println(\"Area:\", shape.Area())\n",
    "        fmt.Println(\"Perimeter:\", shape.Perimeter())\n",
    "    }\n",
    "}\n",
    "\n",
    "// 定义一个结构体\n",
    "type Circle struct {\n",
    "    Radius float64\n",
    "}\n",
    "\n",
    "// Circle 实现 Shape 接口\n",
    "func (c Circle) Area() float64 {\n",
    "    return math.Pi * c.Radius * c.Radius\n",
    "}\n",
    "\n",
    "func (c Circle) Perimeter() float64 {\n",
    "    return 2 * math.Pi * c.Radius\n",
    "}\n",
    "\n",
    "func main() {\n",
    "    c1 := Circle{Radius: 5}\n",
    "    c2 := Circle{Radius: 3}\n",
    "\n",
    "    shapes := []Shape{c1, c2}\n",
    "    processShapes(shapes)\n",
    "}\n",
    "```\n",
    "\n",
    "**解释**\n",
    "\n",
    "- `processShapes` 函数依赖于 `Shape` 接口，而不是具体的 `Circle` 类型。这样，当需要处理其他形状时，只需要让这些形状实现 `Shape` 接口，就可以直接传入 `processShapes` 函数，而不需要修改 `processShapes` 函数的代码，实现了代码的松耦合。\n",
    "\n",
    "**3. 多态性**\n",
    "\n",
    "接口实现了多态性，允许不同的类型以统一的方式被处理。在上述代码中，`printShapeInfo` 函数和 `processShapes` 函数可以处理不同的形状，而不需要关心具体是哪种形状，只需要调用接口中定义的方法即可。\n",
    "\n",
    "**总结**\n",
    "\n",
    "虽然在简单的代码中，不定义接口也能实现相同的功能，但定义接口可以让代码更具灵活性、可扩展性和可维护性，实现代码的复用、依赖倒置和多态性。在实际开发中，尤其是在处理复杂的系统时，接口是一种非常重要的编程工具。 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a95a23ae-9941-4d0f-9aa2-2239d7326ee3",
   "metadata": {},
   "source": [
    "空接口 interface{} 是 Go 的特殊接口，表示所有类型的超集。\n",
    "\n",
    "- 任意类型都实现了空接口。\n",
    "- 常用于需要存储任意类型数据的场景，如泛型容器、通用参数等。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "92a73cb6-e400-47ee-996e-30cf391e55c2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Value: 42, Type: int\n",
      "Value: hello, Type: string\n",
      "Value: 3.14, Type: float64\n",
      "Value: [1 2], Type: []int\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func printValue(val interface{}) {\n",
    "        fmt.Printf(\"Value: %v, Type: %T\\n\", val, val)\n",
    "}\n",
    "\n",
    "func main() {\n",
    "        printValue(42)         // int\n",
    "        printValue(\"hello\")    // string\n",
    "        printValue(3.14)       // float64\n",
    "        printValue([]int{1, 2}) // slice\n",
    "}\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84b0551b-9351-4081-9656-7253a578c9c3",
   "metadata": {},
   "source": [
    "接口组合"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "396cc6ef-3430-4fba-ab7c-33a55d7bd73c",
   "metadata": {},
   "outputs": [
    {
     "ename": "ERROR",
     "evalue": "go/parser internal error: identifier already declared or resolved",
     "output_type": "error",
     "traceback": [
      "go/parser internal error: identifier already declared or resolved"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "type Reader interface {\n",
    "    Read() string\n",
    "}\n",
    "\n",
    "type Writer interface {\n",
    "    Write(data string)\n",
    "}\n",
    "\n",
    "type ReadWriter interface {\n",
    "    Reader\n",
    "    Writer\n",
    "}\n",
    "\n",
    "type File struct{}\n",
    "\n",
    "func (f File) Read() string {\n",
    "    return \"Reading data\"\n",
    "}\n",
    "\n",
    "func (f File) Write(data string) {\n",
    "    fmt.Println(\"Writing data:\", data)\n",
    "}\n",
    "\n",
    "func main() {\n",
    "    var rw ReadWriter = File{}\n",
    "    fmt.Println(rw.Read())\n",
    "    rw.Write(\"Hello, Go!\")\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05531266-1887-42dc-8fa5-3ed8994a26a1",
   "metadata": {},
   "source": [
    "上面这段代码没问题的……vscode运行正常"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "e7ceea8c-8dd4-47a0-9d65-46d56c9d35f2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I am Nokia, I can call you!\n",
      "I am iPhone, I can call you!\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import (\n",
    "    \"fmt\"\n",
    ")\n",
    "\n",
    "type Phone interface {\n",
    "    call()\n",
    "}\n",
    "\n",
    "type NokiaPhone struct {\n",
    "}\n",
    "\n",
    "func (nokiaPhone NokiaPhone) call() {\n",
    "    fmt.Println(\"I am Nokia, I can call you!\")\n",
    "}\n",
    "\n",
    "type IPhone struct {\n",
    "}\n",
    "\n",
    "func (iPhone IPhone) call() {\n",
    "    fmt.Println(\"I am iPhone, I can call you!\")\n",
    "}\n",
    "\n",
    "func phoneCall(phone Phone){\n",
    "    phone.call()\n",
    "}\n",
    "\n",
    "func main() {\n",
    "\n",
    "    phones := [] Phone {NokiaPhone{},new(IPhone)}//new(NokiaPhone)\n",
    "    \n",
    "    for _,p := range phones{\n",
    "        phoneCall(p)\n",
    "    }\n",
    "\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "308566ee-b0fb-47d9-b113-c040977373da",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "var s interface{} = \"hello world\"\n",
    "str,ok := s.(string)\n",
    "ok"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "70f0e697-a44b-413b-8c95-d5d7e2a8db5c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "string\n"
     ]
    }
   ],
   "source": [
    "import \"fmt\"\n",
    "\n",
    "var s interface{} = \"hello world\"\n",
    "switch v := s.(type){\n",
    "    case string:{\n",
    "        fmt.Println(\"string\")\n",
    "        }\n",
    "    default:{\n",
    "        fmt.Println(\"hehe\")\n",
    "    }\n",
    "        \n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6a1571b3-c617-4128-925d-8b6311d1a84c",
   "metadata": {},
   "outputs": [
    {
     "ename": "ERROR",
     "evalue": "repl.go:18:27: cannot convert type <*main.DivideError> to interface <error>: missing method  Error",
     "output_type": "error",
     "traceback": [
      "repl.go:18:27: cannot convert type <*main.DivideError> to interface <error>: missing method  Error"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import (\n",
    "        \"fmt\"\n",
    ")\n",
    "\n",
    "type DivideError struct {\n",
    "        Dividend int\n",
    "        Divisor  int\n",
    "}\n",
    "\n",
    "func (e *DivideError) Error() string {\n",
    "        return fmt.Sprintf(\"cannot divide %d by %d\", e.Dividend, e.Divisor)\n",
    "}\n",
    "\n",
    "func divide(a, b int) (int, error) {\n",
    "        if b == 0 {\n",
    "                return 0, &DivideError{Dividend: a, Divisor: b}\n",
    "        }\n",
    "        return a / b, nil\n",
    "}\n",
    "\n",
    "func main() {\n",
    "        _, err := divide(10, 0)\n",
    "        if err != nil {\n",
    "                fmt.Println(err) // 输出：cannot divide 10 by 0\n",
    "        }\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "77ef3c36-444a-40e9-990c-20ab61c22858",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Item not found\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import (\n",
    "        \"errors\"\n",
    "        \"fmt\"\n",
    ")\n",
    "\n",
    "var ErrNotFound = errors.New(\"not found\")\n",
    "\n",
    "func findItem(id int) error {\n",
    "        return fmt.Errorf(\"database error: %w\", ErrNotFound)\n",
    "}\n",
    "\n",
    "func main() {\n",
    "        err := findItem(1)\n",
    "        if errors.Is(err, ErrNotFound) {\n",
    "                fmt.Println(\"Item not found\")\n",
    "        } else {\n",
    "                fmt.Println(\"Other error:\", err)\n",
    "        }\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "0ffd08de-6d8f-48ee-b40f-39b309a9188b",
   "metadata": {},
   "outputs": [
    {
     "ename": "ERROR",
     "evalue": "repl.go:18:9: cannot convert type <*main.MyError> to interface <error>: missing method  Error",
     "output_type": "error",
     "traceback": [
      "repl.go:18:9: cannot convert type <*main.MyError> to interface <error>: missing method  Error"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import (\n",
    "\t\"errors\"\n",
    "\t\"fmt\"\n",
    ")\n",
    "\n",
    "type MyError struct {\n",
    "\tCode int\n",
    "\tMsg  string\n",
    "}\n",
    "\n",
    "func (e *MyError) Error() string {\n",
    "\treturn fmt.Sprintf(\"Code: %d, Msg: %s\", e.Code, e.Msg)\n",
    "}\n",
    "\n",
    "func getError() error {\n",
    "\treturn &MyError{Code: 404, Msg: \"Not Found\"}\n",
    "}\n",
    "\n",
    "func main() {\n",
    "\terr := getError()\n",
    "\tvar myErr *MyError\n",
    "\tif errors.As(err, &myErr) {\n",
    "\t\tfmt.Printf(\"Custom error - Code: %d, Msg: %s\\n\", myErr.Code, myErr.Msg)\n",
    "\t}\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31ac5b77-66b3-4aa3-811d-88c60ee248dd",
   "metadata": {},
   "source": [
    "**Goroutines：**\n",
    "\n",
    "- Go 中的并发执行单位，类似于轻量级的线程。\n",
    "- Goroutine 的调度由 Go 运行时管理，用户无需手动分配线程。\n",
    "- 使用 go 关键字启动 Goroutine。\n",
    "- Goroutine 是非阻塞的，可以高效地运行成千上万个 Goroutine。\n",
    "\n",
    "**Channel：**\n",
    "\n",
    "- Go 中用于在 Goroutine 之间通信的机制。\n",
    "- 支持同步和数据共享，避免了显式的锁机制。\n",
    "- 使用 chan 关键字创建，通过 <- 操作符发送和接收数据。\n",
    "  \n",
    "**Scheduler（调度器）：**\n",
    "\n",
    "Go 的调度器基于 GMP 模型，调度器会将 Goroutine 分配到系统线程中执行，并通过 M 和 P 的配合高效管理并发。\n",
    "\n",
    "- G：Goroutine。\n",
    "- M：系统线程（Machine）。\n",
    "- P：逻辑处理器（Processor）。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7e23836-d08a-4870-a714-ec5f0b0c608a",
   "metadata": {},
   "source": [
    "https://www.runoob.com/go/go-concurrent.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "46607e9d-9013-46fe-b71e-1bea3bdd58d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func sum(s []int, c chan int) {\n",
    "    sum := 0\n",
    "    for _, v := range s {\n",
    "        sum += v\n",
    "    }\n",
    "    c <- sum // 把 sum 发送到通道 c\n",
    "}\n",
    "\n",
    "func main() {\n",
    "    s := []int{7, 2, 8, -9, 4, 0}\n",
    "\n",
    "    c := make(chan int)\n",
    "    go sum(s[:len(s)/2], c)\n",
    "    go sum(s[len(s)/2:], c)\n",
    "    x, y := <-c, <-c // 从通道 c 中接收\n",
    "\n",
    "    fmt.Println(x, y, x+y)\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9d98964d-e640-435b-8cd9-e838d61e080a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-5 17 12\n"
     ]
    }
   ],
   "source": [
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "224d4a5d-879f-4d3b-a423-04f5c9ca0d21",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 true\n",
      "2 true\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func main() {\n",
    "    // 这里我们定义了一个可以存储整数类型的带缓冲通道\n",
    "    // 缓冲区大小为2\n",
    "    ch := make(chan int, 2)\n",
    "\n",
    "    // 因为 ch 是带缓冲的通道，我们可以同时发送两个数据\n",
    "    // 而不用立刻需要去同步读取数据\n",
    "    ch <- 1\n",
    "    ch <- 2\n",
    "\n",
    "    // 获取这两个数据\n",
    "    fmt.Println(<-ch)\n",
    "    fmt.Println(<-ch)\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "497f08c1-86ef-4eba-95ed-e23da78c9dac",
   "metadata": {},
   "outputs": [
    {
     "ename": "ERROR",
     "evalue": "repl.go:7:10: expected '(', found 'IDENT' f",
     "output_type": "error",
     "traceback": [
      "repl.go:7:10: expected '(', found 'IDENT' f"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func main() {\n",
    "    ch := make(chan int)\n",
    "    func f(ch chan int) {\n",
    "        ch <- 1\n",
    "        ch <- 2\n",
    "        \n",
    "    }\n",
    "    go f(ch)\n",
    "    num :=<-ch\n",
    "    fmt.Println(num)\n",
    "    num =<-ch\n",
    "    fmt.Println(num)\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "4e67e18a-dbe0-4846-833f-8450443af566",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func main() {\n",
    "    ch := make(chan int)\n",
    "    go func(ch chan int) {\n",
    "        ch <- 1\n",
    "        ch <- 2\n",
    "        \n",
    "    }(ch)\n",
    "    num :=<-ch\n",
    "    fmt.Println(num)\n",
    "    num =<-ch\n",
    "    fmt.Println(num)\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "17b5aef2-8124-4b44-b3b1-31568607cb7a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func f(ch chan int) {\n",
    "        ch <- 1\n",
    "        ch <- 2\n",
    "        \n",
    "    }\n",
    "\n",
    "func main() {\n",
    "    ch := make(chan int)\n",
    "    go f(ch)\n",
    "    num :=<-ch\n",
    "    fmt.Println(num)\n",
    "    num =<-ch\n",
    "    fmt.Println(num)\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22874362-5a7b-46cd-a982-dfa153f1bdb7",
   "metadata": {},
   "source": [
    "**注意:**<mark> 又是奇奇怪怪的问题，后面两种方式能够正常运行，第一种方式运行报错。</mark>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "1623ae88-01e9-45a8-9738-14d25c31dfb6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "1\n",
      "2\n",
      "3\n",
      "5\n",
      "8\n",
      "13\n",
      "21\n",
      "34\n",
      "55\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func fibonacci(ch chan int){\n",
    "    x,y := 1,1\n",
    "    n := cap(ch)\n",
    "    for i:=0;i<n;i++{\n",
    "        ch <- x\n",
    "        x,y = y,x+y\n",
    "    }\n",
    "    close(ch)\n",
    "}\n",
    "\n",
    "func main(){\n",
    "    ch := make(chan int,10)\n",
    "    fibonacci(ch)\n",
    "    for i:= range ch{\n",
    "        fmt.Println(i)\n",
    "    } \n",
    "}\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "42d91dcc-a3bd-4769-b8c1-604bb13cbd1d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 true\n",
      "1 true\n",
      "2 true\n",
      "3 true\n",
      "5 true\n",
      "8 true\n",
      "13 true\n",
      "21 true\n",
      "34 true\n",
      "55 true\n",
      "quit\n"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import \"fmt\"\n",
    "\n",
    "func fibonacci(c, quit chan int) {\n",
    "    x, y := 1, 1\n",
    "    for {\n",
    "        select {\n",
    "        case c <- x:\n",
    "            x, y = y, x+y\n",
    "        case <-quit:\n",
    "            fmt.Println(\"quit\")\n",
    "            return\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "func main() {\n",
    "    c := make(chan int)\n",
    "    quit := make(chan int)\n",
    "\n",
    "    go func() {\n",
    "        for i := 0; i < 10; i++ {\n",
    "            fmt.Println(<-c)\n",
    "        }\n",
    "        quit <- 0\n",
    "    }()\n",
    "    fibonacci(c, quit)\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "df90d9b1-4199-4116-8690-b79bb150c676",
   "metadata": {},
   "outputs": [
    {
     "ename": "ERROR",
     "evalue": "Converter.Type(): unsupported types.Type: *types.TypeParam",
     "output_type": "error",
     "traceback": [
      "Converter.Type(): unsupported types.Type: *types.TypeParam"
     ]
    }
   ],
   "source": [
    "package main\n",
    "\n",
    "import (\n",
    "        \"fmt\"\n",
    "        \"sync\"\n",
    ")\n",
    "\n",
    "func worker(id int, wg *sync.WaitGroup) {\n",
    "        defer wg.Done() // Goroutine 完成时调用 Done()\n",
    "        fmt.Printf(\"Worker %d started\\n\", id)\n",
    "        fmt.Printf(\"Worker %d finished\\n\", id)\n",
    "}\n",
    "\n",
    "func main() {\n",
    "        var wg sync.WaitGroup\n",
    "\n",
    "        for i := 1; i <= 3; i++ {\n",
    "                wg.Add(1) // 增加计数器\n",
    "                go worker(i, &wg)\n",
    "        }\n",
    "\n",
    "        wg.Wait() // 等待所有 Goroutine 完成\n",
    "        fmt.Println(\"All workers done\")\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ee18895-57a0-463c-abca-87c196d1a57f",
   "metadata": {},
   "source": [
    "```shell\n",
    "Worker 3 started\n",
    "Worker 3 finished\n",
    "Worker 2 started\n",
    "Worker 2 finished\n",
    "Worker 1 started\n",
    "Worker 1 finished\n",
    "All workers done\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33a4c7ab-ebc4-4298-9915-13079ff137eb",
   "metadata": {},
   "source": [
    "**sync.WaitGroup 用于等待多个 Goroutine 完成。**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c043033c-1d99-4002-ae18-e151ee6a444e",
   "metadata": {},
   "source": [
    "Go 语言通过 Goroutine 和 Channel 提供了强大的并发支持，简化了传统线程模型的复杂性。配合调度器和同步工具，可以轻松实现高性能并发程序。\n",
    "\n",
    "- Goroutines 是轻量级线程，使用 go 关键字启动。\n",
    "- Channels 用于 goroutines 之间的通信。\n",
    "- Select 语句 用于等待多个 channel 操作。\n",
    "\n",
    "**死锁 (Deadlock)：**\n",
    "\n",
    "- 示例：所有 Goroutine 都在等待，但没有任何数据可用。\n",
    "- 解决：避免无限等待、正确关闭通道。\n",
    "\n",
    "**数据竞争 (Data Race)：**\n",
    "\n",
    "- 示例：多个 Goroutine 同时访问同一变量。\n",
    "- 解决：使用 Mutex 或 Channel 同步访问。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1c1741ab-41fe-4070-acfb-ec882c1d4c16",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Go",
   "language": "go",
   "name": "gophernotes"
  },
  "language_info": {
   "codemirror_mode": "",
   "file_extension": ".go",
   "mimetype": "",
   "name": "go",
   "nbconvert_exporter": "",
   "pygments_lexer": "",
   "version": "go1.24.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
